home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / GameKit / Examples / PacMan / Maze.m < prev    next >
Text File  |  1995-06-12  |  7KB  |  291 lines

  1.  
  2. #import <stdio.h>
  3. #import <libc.h>
  4. #import "Maze.h"
  5. #import "PacManGameBrain.h"
  6. #import <appkit/appkit.h>
  7.  
  8. @implementation Maze
  9.  
  10. - init
  11. {
  12.     char *appPath, *slashPos;
  13.     int i, j, k;
  14.     FILE *fp;
  15.     
  16.     [super init];
  17.     
  18.     // load image
  19.     mazeParts[1] = [NXImage findImageNamed:"Maze.tiff"];
  20.     mazeParts[2] = [NXImage findImageNamed:"MazeBig.tiff"];
  21.     
  22.     scale = 1;
  23.     
  24.     // get the path to the app wrapper (to find the maze file)
  25.     appPath = (char *)malloc(1024);
  26.     strcpy(appPath, NXArgv[0]);
  27.     if (slashPos = strrchr(appPath, '/')) {
  28.         slashPos[1] = '\0';
  29.     } else {
  30.         strcpy(appPath, "./");
  31.     }
  32.     strcat(appPath, "mazes");
  33.     
  34.     // read in the maze data
  35.     fp = fopen(appPath, "r");
  36.     if (fp == NULL) fprintf(stderr, "PacMan:  Cannot read maze data!\n");
  37.     for (i=0; i<MAZES; i++) {
  38.         for (j=BLOCK_HEIGHT-1; j>=0; j--) {
  39.             for (k=0; k<BLOCK_WIDTH; k++) {
  40.                 mazes[i][k][j] = getc(fp);
  41.                 switch(mazes[i][k][j]) { // handle special cases
  42.                     case 'D' : { mazes[i][k][j] = 5; // Door
  43.                                 break; }
  44.                     case '>' : { mazes[i][k][j] = 26; // door cap
  45.                                 break; }
  46.                     case '<' : { mazes[i][k][j] = 27; // door cap
  47.                                 break; }
  48.                     case ']' : { mazes[i][k][j] = 33; // end cap
  49.                                 break; }
  50.                     case '[' : { mazes[i][k][j] = 32; // end cap
  51.                                 break; }
  52.                     case ' ' : { mazes[i][k][j] = 28; // dot
  53.                                 break; }
  54.                     case 'O' : { mazes[i][k][j] = 29; // power dot
  55.                                 break; }
  56.                     case '|' : { mazes[i][k][j] = 31; // vert wall
  57.                                 break; }
  58.                     case '-' : { mazes[i][k][j] = 30; // horiz wall
  59.                                 break; }
  60.                     case '^' : { mazes[i][k][j] = 34; // end cap
  61.                                 break; }
  62.                     case 'P' : { mazes[i][k][j] = 7; // player (blank image)
  63.                                 break; }
  64.                     case 'G' : { mazes[i][k][j] = 10; // ghost (blank image)
  65.                                 break; }
  66.                     case '+' : { mazes[i][k][j] = 8; // blank (inside cage)
  67.                                 break; }
  68.                     default  : { mazes[i][k][j] -= 'a'; // get index
  69.                                 break; }
  70.                 }
  71.             }
  72.             getc(fp);
  73.         }
  74.     }
  75.     fclose(fp);
  76.     
  77.     // initizlize other instance vars.
  78.     [self makeMaze:1];
  79.     powerDotShown = YES;
  80.     visibleMaze = YES;
  81.     
  82.     return self;
  83. }
  84.  
  85.  
  86. - render:(NXRect *)rect at:(NXPoint *)pos     // used to render in another view
  87. {
  88.     int j, k;
  89.     NXRect from, check;
  90.     NXPoint pos2;
  91.     
  92.     if (!visibleMaze) return self;
  93.     for (j=0; j<BLOCK_HEIGHT; j++) {
  94.         pos2.y = j * GHOST_SIZE * scale + pos->y;
  95.         for (k=0; k<BLOCK_WIDTH; k++) {
  96.             if ((maze[k][j] != POWER) || powerDotShown) {    // if power dot
  97.                 // blinked off, we don't render it.
  98.                 NXSetRect(&check, k * GHOST_SIZE, j * GHOST_SIZE,
  99.                     GHOST_SIZE, GHOST_SIZE);
  100.                 if (NXIntersectsRect(&check, rect)) { // only draw maze bits
  101.                     // in the rects that intersect the rect passed to us
  102.                     NXSetRect(&from,
  103.                         (maze[k][j] % PER_ROW) * GHOST_SIZE * scale,
  104.                         (maze[k][j] / PER_ROW) * GHOST_SIZE * scale,
  105.                         GHOST_SIZE * scale, GHOST_SIZE * scale);
  106.                     pos2.x = k * GHOST_SIZE * scale + pos->x;
  107.                     [mazeParts[scale] composite:NX_SOVER
  108.                         fromRect:&from toPoint:&pos2];
  109.     }    }    }    }
  110.     return self;
  111.  
  112. }
  113.  
  114.  
  115. - makeMaze:(int)num
  116. {    // build a maze from the template; fill it with dots, set up new player and
  117.     // ghost positions, etc.
  118.     int j, k;
  119.     int ghost = 0;
  120.     int pdot = 0;
  121.     
  122.     dots = 0;
  123.     if ((num >= 0) && (num < MAZES)) { // make sure in range
  124.         mazeNum = num;
  125.         player[0] = -32; player[1] = -32; // sum is neg if no player spot found
  126.         // set up player/ghost/power dot position, etc. for maze.
  127.         for (j=0; j<BLOCK_HEIGHT; j++) {
  128.             for (k=0; k<BLOCK_WIDTH; k++) {
  129.                 maze[k][j] = mazes[num][k][j];
  130.                 switch (maze[k][j]) {
  131.                     case GHDOOR  : {    door[0] = k;    // door for ghosts
  132.                         door[1] = j; break; }
  133.                     case PLAYER  : { player[0] = k;        // Player
  134.                         player[1] = j;
  135.                         maze[k][j] = EMPTY; break; }
  136.                     case GHOST : { ghosts[ghost * 2] = k;    // Ghost
  137.                         ghosts[ghost * 2 + 1] = j;
  138.                         maze[k][j] = EMPTY;
  139.                         if (++ghost > MAX_GHOSTS) { fprintf(stderr,
  140.                             "Maze %d has too many ghosts.\n", num); }
  141.                         break; }
  142.                     case POWER : { power[pdot * 2] = k;    // Power Dot
  143.                         power[pdot * 2 + 1] = j; dots++;
  144.                         if (++pdot > MAX_POWER_DOTS) { fprintf(stderr,
  145.                             "Maze %d has too many power dots.\n", num); }
  146.                         break; }
  147.                     case DOT : { dots++;                    // Normal Dot
  148.                         break; }
  149.                     default : { break; }                // do nothing
  150.                 }
  151.             }
  152.         }
  153.         if (!ghost) { fprintf(stderr, "Maze %d has no ghosts.\n", num); }
  154.         if (!pdot) { fprintf(stderr, "Maze %d has no power dots.\n", num); }
  155.         if (player[0]+player[1] < 0) {
  156.             fprintf(stderr, "Maze %d has no player.\n", num); }
  157.     }
  158.     return self;
  159. }
  160.  
  161.  
  162. - playerPosition:(int *)x :(int *)y    // return x, y of player/fruit
  163. {
  164.     *x = player[0] * GHOST_SIZE; *y = player[1] * GHOST_SIZE;
  165.     return self;
  166. }
  167.  
  168.  
  169. - doorPosition:(int *)x :(int *)y    // return x, y of door to ghost chamber
  170. {
  171.     *x = door[0] * GHOST_SIZE; *y = door[1] * GHOST_SIZE;
  172.     return self;
  173. }
  174.  
  175.  
  176. - (const int *)powerDot            // return pointer to power array
  177. {
  178.     return power;
  179. }
  180.  
  181.  
  182. - (const int *)ghosts                // return pointer to ghosts array
  183. {
  184.     return ghosts;
  185. }
  186.  
  187.  
  188. - (BOOL)powerDotAt:(int)x :(int)y    // return YES if power dot in block
  189. {
  190.     // only have to be 1/2 way into block to eat dot:
  191.     int basex = x / GHOST_SIZE + ((x % GHOST_SIZE) > (GHOST_SIZE / 2));
  192.     int basey = y / GHOST_SIZE + ((y % GHOST_SIZE) > (GHOST_SIZE / 2));
  193.     
  194.     if (maze[basex][basey] == POWER) { // munch power dot
  195.         [[[NXApp delegate] scoreKeeper] addToScore:POWERDOTPOINTS];
  196.         maze[basex][basey] = EMPTY;
  197.         dots--;
  198.         dotx = basex; doty = basey;    // save them away
  199.         return YES;
  200.     }
  201.     return NO;
  202. }
  203.  
  204. - (BOOL)eatDotAt:(int)x :(int)y        // return YES if OK, NO if no dot was there
  205. {
  206.     int basex = x / GHOST_SIZE;
  207.     int basey = y / GHOST_SIZE;
  208.     int dx = x % GHOST_SIZE;
  209.     int dy = y % GHOST_SIZE;
  210.     
  211.     if (!dx) { // in a vertical column or corner/junction
  212.         if (dy > GHOST_SIZE / 2) basey++;
  213.     } else { // on a horiz. row
  214.         if (dx > GHOST_SIZE / 2) basex++;
  215.     }
  216.     
  217.     if (maze[basex][basey] == DOT) { // munch dot
  218.         [[[NXApp delegate] scoreKeeper] addToScore:DOTPOINTS];
  219.         maze[basex][basey] = EMPTY;
  220.         dots--;
  221.         dotx = basex; doty = basey;    // save them away
  222.         return YES;
  223.     }
  224.     return NO;
  225. }
  226.  
  227. - (int)dots                            // return the number of dots left in maze
  228. {
  229.     return dots;
  230. }
  231.  
  232. - lastDot:(int *)xx :(int *)yy
  233. {
  234.     *xx = dotx * GHOST_SIZE;
  235.     *yy = doty * GHOST_SIZE;
  236.     return self;
  237. }
  238.  
  239. - (BOOL)playerWall:(float)x :(float)y    // YES if player can't be in block
  240. {
  241.     int mazex = x / GHOST_SIZE;
  242.     int mazey = y / GHOST_SIZE;
  243.     
  244.     if ((maze[mazex][mazey] == EMPTY)    ||
  245.         (maze[mazex][mazey] == DOT)        ||
  246.         (maze[mazex][mazey] == POWER)) return NO;
  247.     return YES;
  248. }
  249.  
  250. - (BOOL)monsterWall:(float)x :(float)y    // YES if ghost can't be in block
  251. {
  252.     int mazex = x / GHOST_SIZE;
  253.     int mazey = y / GHOST_SIZE;
  254.     
  255.     if ((maze[mazex][mazey] == EMPTY)    ||
  256.         (maze[mazex][mazey] == DOT)        ||
  257.         (maze[mazex][mazey] == GHDOOR)    ||
  258.         (maze[mazex][mazey] == POWER)) return NO;
  259.     return YES;
  260. }
  261.  
  262. - blinkPowerDot                    // toggle ON/OFF state of power dots
  263. {
  264.     powerDotShown = !powerDotShown;
  265.     return self;
  266. }
  267.  
  268. - visible:(BOOL)flag                // used to tell us if the maze is visible
  269. {
  270.     visibleMaze = flag;
  271.     return self;
  272. }
  273.  
  274. - (BOOL)isVisible;                    // used to tell others if maze is visible
  275. { return visibleMaze; }
  276.  
  277. - (int)scale
  278. {
  279.     return scale;
  280. }
  281.  
  282. - setScale:(int)newScale
  283. {
  284.     if ((newScale < 1) || (newScale > 2)) return self;
  285.     scale = newScale;
  286.     return self;
  287. }
  288.  
  289.  
  290. @end
  291.